﻿//
// Created by QU on 24-9-28.
//

#include "client/simple_client/simple_client.h"

#include "node/Node.h"
#include "server/logic/MSGID.h"

#include <iostream>
#include <iomanip>

#include <boost/endian/conversion.hpp>

SimpleClient::SimpleClient(boost::asio::io_context& io_context, const std::string& host, const std::string& port,
                           uint16_t min_payload_size, uint16_t max_payload_size)
    : socket_(io_context),
      min_payload_size_(min_payload_size),
      max_payload_size_(max_payload_size),
      random_engine_(std::chrono::system_clock::now().time_since_epoch().count())
{
    tcp::resolver resolver(io_context);
    auto endpoints = resolver.resolve(host, port);
    boost::asio::connect(socket_, endpoints);
    std::cout << "Connected to " << host << ":" << port << std::endl;
}

void SimpleClient::send_random_data()
{
    std::uniform_int_distribution<> type_dist(0, 255);
    std::uniform_int_distribution<> payload_size_dist(min_payload_size_, max_payload_size_);

    uint8_t type_tag = type_dist(random_engine_);
    uint8_t msg_id = static_cast<uint8_t>(MSGID::MSG_HELLO_WORLD);
    uint16_t payload_size = payload_size_dist(random_engine_);

    Node node(payload_size, type_tag, msg_id);

    // Generate random payload
    std::vector<uint8_t> payload(payload_size);
    std::uniform_int_distribution<> byte_dist(0, 255);
    std::ranges::generate(payload, [&]() { return byte_dist(random_engine_); });
    node.setPayload(reinterpret_cast<const std::byte*>(payload.data()), payload_size);

    auto serialized_data = node.serialize();
    std::cout << "[debug] SendBuffer size: " << node.getNodeFullSize() << std::endl;
    boost::asio::write(socket_, boost::asio::buffer(serialized_data.buffer.get(), serialized_data.length));

    std::cout << "Sent data: Type Tag = " << static_cast<int>(type_tag)
        << ", Message ID = " << static_cast<int>(msg_id)
        << ", Payload Size = " << payload_size << " bytes" << std::endl;
    std::cout << node;
}

void SimpleClient::receive_data()
{
    std::vector<char> header_buffer(Node::MAX_HEADER_SIZE);
    boost::system::error_code ec;

    // 读取头部
    size_t bytes_transferred = boost::asio::read(socket_,
        boost::asio::buffer(header_buffer, Node::MAX_HEADER_SIZE), ec);

    if (ec)
    {
        std::cout << "Error receiving header: " << ec.message() << std::endl;
        return;
    }

    if (bytes_transferred < Node::MAX_HEADER_SIZE)
    {
        std::cout << "Incomplete header received" << std::endl;
        return;
    }

    // 解析 payload size
    const uint16_t payload_size = boost::endian::big_to_native(
        *reinterpret_cast<uint16_t*>(&header_buffer[2]));

    std::cout << "Received header: payload_size: " << payload_size << " bytes." << std::endl;

    // 读取 payload
    std::vector<std::byte> payload_buffer(payload_size);
    bytes_transferred = boost::asio::read(socket_,
        boost::asio::buffer(payload_buffer, payload_size), ec);

    if (ec)
    {
        std::cout << "Error receiving payload: " << ec.message() << std::endl;
        return;
    }

    if (bytes_transferred < payload_size)
    {
        std::cout << "Incomplete payload received" << std::endl;
        return;
    }

    // 打印 payload 内容
    printBuffer(std::cout, payload_buffer, payload_size);
}

std::ostream& SimpleClient::printBuffer(std::ostream& os, const std::vector<std::byte>& buffer, const size_t buffer_size,
                                   const size_t header_size)
{
    constexpr size_t OUTPUT_HEAD_TAIL = 16;
    os << "Session::printBuffer()\n";
    os << "Buffer size: " << buffer_size << " Payload size: " << buffer_size - header_size << "\n";
    os << "Header (hex): ";
    os << std::hex << std::setfill('0');
    for (size_t i = 0; i < header_size; ++i)
    {
        if (i > 0) os << " ";
        os << std::setw(2) << static_cast<int>(buffer[i]);
    }
    os << "\n";

    os << "Payload (hex): ";
    for (size_t i = header_size; i < buffer_size && i < header_size + OUTPUT_HEAD_TAIL; ++i)
    {
        if (i > header_size) os << " ";
        os << std::setw(2) << static_cast<int>(buffer[i]);
    }
    if (buffer_size > header_size + OUTPUT_HEAD_TAIL) { os << " ..."; } // 如果buffer超过32字节，添加省略号
    for (size_t i = std::max(buffer_size - OUTPUT_HEAD_TAIL, header_size + OUTPUT_HEAD_TAIL); i < buffer_size; ++i)
    {
        if (i > header_size) os << " ";
        os << std::setw(2) << static_cast<int>(buffer[i]);
    }
    os << std::dec << "\n"; // 恢复为十进制输出

    return os;
}



int main(int argc, char* argv[])
{
    if (argc != 5 && argc != 6)
    {
        std::cerr << "Usage: client <host> <port> <min_payload_size> <max_payload_size> [interval_ms]" << std::endl;
        return 1;
    }

    try
    {
        boost::asio::io_context io_context;

        std::string host = argv[1];
        std::string port = argv[2];
        uint16_t min_payload_size = static_cast<uint16_t>(std::stoi(argv[3]));
        uint16_t max_payload_size = static_cast<uint16_t>(std::stoi(argv[4]));

        int interval_ms = 2000;  // 默认间隔
        if (argc == 6) {
            interval_ms = std::stoi(argv[5]);
        }

        SimpleClient client(io_context, host, port, min_payload_size, max_payload_size);

        for(;;)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms));
            client.send_random_data();
            std::this_thread::sleep_for(std::chrono::milliseconds(10));

            // 发送后立即尝试接收响应
            client.receive_data();
            std::cout << std::endl;
        }
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    return 0;
}